package com.github.tommas.admintpl.common;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

public class GlobalHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
    public GlobalHandlerExceptionResolver() {
        setWarnLogCategory(getClass().getName());
    }

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        MappingJackson2JsonView view = new MappingJackson2JsonView();
        view.setExtractValueFromSingleKeyModel(true);

        CommonResult result;
        if (ex instanceof UnauthorizedException) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            result = CommonResult.failed(String.format("You don`t have permission to access uri: %s", request.getRequestURI()));
        } else if (ex instanceof ServiceException) {
            ServiceException e = (ServiceException) ex;
            result = new CommonResult(e.getCode(), e.getMessage());
        } else {
            result = CommonResult.failed();
        }

        Map<String, CommonResult> model = new HashMap<>();
        model.put(this.getClass().getName(), result);

        return new ModelAndView(view, model);
    }

    @Override
    protected String buildLogMessage(Exception ex, HttpServletRequest request) {
        if (ex instanceof UnauthorizedException) {
            Subject subject = SecurityUtils.getSubject();
            return String.format("%s try to access uri: %s", subject.getPrincipal(), request.getRequestURI());
        }

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);

        String msg = super.buildLogMessage(ex, request);
        msg += "\nStack Trace:\n" + sw;

        return msg;
    }
}
